package db_main

import (
	"errors"
	"fmt"
	"log"
	global2 "longmen/server/config/global"
	"longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql"
	"longmen/server/pkg/db/mysql/models/models_main"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm"
	"longmen/server/pkg/common/api_models"
)

func GetGuildParam(param map[string]interface{}) (*models_main.Guild, error) {
	fName := "GetGuildParam"
	o := &models_main.Guild{}
	table := global2.Live().Model(&models_main.Guild{})
	mysql.Condition(table, param, "", "", 0, 0)
	err := table.Find(o).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	return o, err
}

func GetGuildsParam(param map[string]interface{}, order string, page, size int) ([]*models_main.Guild, error) {
	fName := "GetGuildsParam"
	o := make([]*models_main.Guild, 0)
	table := global2.Live().Model(&models_main.Guild{})
	mysql.Condition(table, param, "", order, page, size)
	err := table.Find(&o).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	if err != nil {
		err = fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	return o, err
}

func UpdateGuildByTransactions(session *gorm.DB, columns []string, guild *models_main.Guild) error {
	fName := "UpdateGuildByTransactions"
	err := session.Where("id = ?", guild.Id).Select(columns).Updates(guild).Error
	if err != nil {
		session.Rollback()
		return fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	return nil
}

/**
@Create Enzo July02 2022
通一个礼物，计算公会分红
*/
func UpdateGuildShareFromGift(gift models_main.GiftLog, managerList []api_models.ManagerRate) (err error) {
	tx := global2.Live().Begin()
	//让我们一起回滚
	for _, v := range managerList {
		err = UpdateGuildManagerDiamond(tx, v, gift) //子过程里有错就会回滚
		if err != nil {
			global2.Log.Warnf("[Account]送礼订单%s分成失败", gift.Id)
			return err
		}
	}
	return tx.Commit().Error //同一笔送礼订单对应的各笔分成，一损俱损，如果对账发现少了，需要在log中查找对应的送礼订单
}

/**
@Create Spicy
@Modify 2022July02 Enzo 把session放到外面（每个礼物一起回滚, 要补记录的话以每个礼物为单位）
*/
func UpdateGuildManagerDiamond(tx *gorm.DB, manager api_models.ManagerRate, gift models_main.GiftLog) (err error) {
	if manager.ShareAmount < 1 {
		return nil //可能中间有的经纪人分到0，这个是正常的，不用处理
	}
	log.Println("get_share_diamond:", manager.ShareAmount)
	err = tx.Model(&models_main.GuildManager{}).
		Where("id = ?", manager.ManagerId).
		Updates(map[string]interface{}{
			"diamond":       gorm.Expr("diamond+?", manager.ShareAmount),
			"total_diamond": gorm.Expr("total_diamond+?", manager.ShareAmount)}).
		Error
	if err != nil {
		tx.Rollback()
		return err
	}
	// 写入公会分成记录
	fShareAmount := float64(manager.ShareAmount) / 100
	var guildProfit = &models_main.GuildProfit{
		GuildId:        manager.GuildId,
		GuildManagerId: manager.ManagerId,
		Diamond:        manager.ShareAmount,
		Content:        fmt.Sprintf("旗下主播(ID:%d)直播(ID:%d)收益分红：%.2f克拉", gift.Anchorid, gift.Liveid, fShareAmount),
		CreateTime:     time.Now(),
		GiftTime:       gift.CreateTime,
		GiftLogId:      gift.Id,
	}

	err = tx.Create(&guildProfit).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	return nil

}

func UpdateAnchorDiamond(anchor *models_main.User, diamond int) {
	log.Println("lastDiamond:", diamond)
	UpdateAmount(anchor.Id, diamond, _const.CoinDiamond, _const.PROFIT_COMMISSION_ANCHOR)
}

/**
@Create Jun-30-2022 Enzo
传入主播的uid
返回：该公会的分成比例（公会能从礼物中得多少）， [超管比例，经纪人1分成比例, 经纪人2分成比例, ...], error
*/
func QueryAndCalcAnchorRate(anchorID int) (float64, *[]api_models.ManagerRate, error) {
	// 主播工会及经纪人信息
	var anchor *models_main.User

	managerList := make([]api_models.ManagerRate, 0)
	err := global2.GetX().Model(&models_main.User{}).Where("id = ?", anchorID).Find(&anchor).Error

	if err != nil {
		return 0, nil, err
	}
	if anchor.GuildId == 0 {
		return 0, nil, fmt.Errorf("主播无公会")
	}
	// 工会信息
	var guild *models_main.Guild
	err = global2.Live().Model(&models_main.Guild{}).Where("id = ?", anchor.GuildId).Find(&guild).Error
	if err != nil {
		return 0, nil, err
	}
	if guild.Id == 0 {
		return 0, nil, fmt.Errorf("工会ID不存在")
	}
	// 经纪人信息
	var guildManager *models_main.GuildManager
	err = global2.Live().Model(&models_main.GuildManager{}).Where("id = ?", anchor.GuildManagerId).Find(&guildManager).Error
	if err != nil {
		return 0, nil, err
	}
	global2.Log.Debug("guildManager:", guildManager)
	global2.Log.Debug("PathIDS:", guildManager.PathIds)
	// role id 上往下分
	var guildManagers []*models_main.GuildManager
	var ids = strings.Split(guildManager.PathIds, ",") //0, 25, 36
	ids = append(ids, strconv.Itoa(anchor.GuildManagerId))
	err = global2.Live().Model(&models_main.GuildManager{}).Where("id in (?)", ids).Order("role_id asc").Find(&guildManagers).Error

	if err != nil {
		return 0, nil, err
	}

	// 工会分成
	var guildShareRate = string2.Round(float64(guild.SharingRatio)/100, 6)

	global2.Log.Debugf("工会%d分成:%g", guild.Id, guildShareRate)

	var remainingRate = guildShareRate

	// 如果直属第一层超管, 超管直接拿掉主播剩余的
	if len(guildManagers) == 1 && guildManagers[0].RoleId == 1 {
		var parent *models_main.GuildManager
		err = global2.Live().Model(&models_main.GuildManager{}).Where("id = ?", anchor.GuildManagerId).Find(&parent).Error
		if err != nil {
			err = errors.New(fmt.Sprintf("经纪人%d找不到", anchor.GuildManagerId))
			global2.Log.Warn(err)
			return 0, nil, err
		}
		remainingRate = string2.Round(remainingRate*float64(anchor.SharingRatio)/100, 6)
		//上级剩下的钱 - 下级要拿的比例 = 上级本人可得的
		managerList = append(managerList,
			api_models.ManagerRate{
				ManagerId: guildManagers[0].Id,
				GuildId:   anchor.GuildId,
				Rate:      guildShareRate - remainingRate})
		global2.Log.Debugf("经纪人就是超管，最终主播分成:%g", remainingRate)
	} else {
		guildManagers = append(guildManagers, &models_main.GuildManager{
			Id:           anchor.Id, //这个是便于计算，把主播也加入列表里
			ParentId:     anchor.GuildManagerId,
			SharingRatio: anchor.SharingRatio,
		})
		managerRate := 1.0 //超管可分配资金为公会的100%
		for _, v := range guildManagers {
			if v.RoleId != 1 { //超管不计算的，每次是推当前经纪人的上级进队列
				global2.Log.Debug("current_id:", v.Id)
				global2.Log.Debug("share_ratio:", v.SharingRatio)
				var parent *models_main.GuildManager
				//验证一下他的上级存不存在
				err = global2.Live().Model(&models_main.GuildManager{}).Where("id = ?", v.ParentId).Find(&parent).Error

				if err != nil {
					err = errors.New(fmt.Sprintf("分成：经纪人%d上级出错%v", v.Id, err))
					global2.Log.Warnf("%v", err)
					return 0, nil, err
				}

				managerRate = float64(v.SharingRatio) / 100
				if !util.ValidRange(_const.VALUE_MANAGER_RATE, managerRate) {
					err = errors.New(fmt.Sprintf("分成：经纪人%d分成比例出错%v", v.Id, err))
					global2.Log.Warnf("%d", err)
					return 0, nil, err
				}

				tmpRemainingRate := string2.Round(remainingRate*managerRate, 6) //当前等级要拿的比例
				managerList = append(managerList,
					api_models.ManagerRate{ //parent(上级)本人可得的 = 上级可支配比例 - 当前级要拿的比例
						ManagerId: v.ParentId,
						GuildId:   anchor.GuildId,
						Rate:      remainingRate - tmpRemainingRate})
				remainingRate = tmpRemainingRate
				if !util.ValidRange(_const.VALUE_MANAGER_RATE, remainingRate) { //剩下的不能少于1%
					err = errors.New(fmt.Sprintf("工会%d分成配置有错", guild.Id))
					global2.Log.Debugf("%v", err)
					return 0, nil, err
				}
			}

			global2.Log.Debugf("分成：经纪人%d可分配比例%g", v.Id, managerRate)
			global2.Log.Debugf("事到如今还剩%g", remainingRate)
		} //end for
	} //fi
	global2.Log.Debug("[Account]sharePlan:", managerList, " for anchor:", remainingRate)
	return guildShareRate, &managerList, nil

}
